package com.sailor.config;


import cn.hutool.core.io.resource.ResourceUtil;
import com.sailor.util.EnvTools;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.boot.logging.DeferredLog;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.InputStreamResource;

import java.io.InputStream;
import java.util.List;

/**
 * 读取公共配置文件处理类
 * @author Sailor
 * @date 2022-11-14 16:33:30
 */
@Order(Ordered.LOWEST_PRECEDENCE)
public class CommonEnvironmentPostProcessor implements EnvironmentPostProcessor, ApplicationListener<ApplicationEvent> {


    private static final String DEFAULT_NAMES = "application";

    private static final String CONFIG_LOCATION_PROPERTY = "spring.config.location";

    private static final String COMMON_FILE_SUFFIX = "common";

    private static final DeferredLog LOGGER = new DeferredLog();

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        LOGGER.info("common env load start");
        YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
        try {
            String path;
            String pathSuffix = DEFAULT_NAMES + "-"
                    + COMMON_FILE_SUFFIX + "."
                    + sourceLoader.getFileExtensions()[0];
            InputStream resourceAsStream;
            // 适配本地启动配置环境--spring.config.location=classpath:/local/
            if (environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {
                path = environment.getProperty(CONFIG_LOCATION_PROPERTY) + pathSuffix;
                resourceAsStream = ResourceUtil.getStream(path);
            } else {
                // application-common.yml
                path = "/" + EnvTools.runtime().name().toLowerCase() + "/" + pathSuffix;
                resourceAsStream = this.getClass().getResourceAsStream(path);
            }


            LOGGER.info("common file path:" + path);


            List<PropertySource<?>> load =
                    sourceLoader.load(DEFAULT_NAMES + "-" + COMMON_FILE_SUFFIX,
                            new InputStreamResource(resourceAsStream));
            for (PropertySource<?> propertySource : load) {
                // 放在最后面 这样项目中的配置会优先被获取 私有配置可以覆盖公共配置
                environment.getPropertySources().addLast(propertySource);
            }
            resourceAsStream.close();

        } catch (Exception e) {
            LOGGER.error("common env load fail", e);
        }

    }

    /**
     * Handle an application event.
     *
     * @param event the event to respond to
     */
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        // EnvironmentPostProcessor 的执行比较早，这个时候日志系统根本就还没有初始化，
        // 所以在此之前的日志操作都不会有效果，使用 DeferredLog 缓存日志；并在合适的时机回放日志
        LOGGER.replayTo(CommonEnvironmentPostProcessor.class);
    }
}
